% Recover training data
Option.E = 0.8;  %   E: double, the range is (0.5, 1), the threshold
Option.C = 0.2;  %   C: double, the range is (0, 0.5), the updating range
Option.T = 5;
Option.K = 10;
Option.IncludeInstanceItself = true;
Option.CombineLabel = false;
ExperimentTimes = 5;

if(Option.IncludeInstanceItself == true)
    KNNList = Ddavid_find_knn_from_training_data(Option.K, AllDataTraining, AllDataTraining);
else
    KNNList = Ddavid_find_knn(Option.K, AllDataTraining);
end

AvgHammingTraining = 0.0;
AvgHammingTestingAllSampledRecovered = 0.0;
AvgHammingTrainingII = 0.0;
AvgHammingTestingAllSampledRecoveredII = 0.0;

for i = 1:ExperimentTimes
    % Recover training labels without II
    Option.IncludeInstanceItself = false;

    [RecoveredResult] = Ddavid_kNN_recover_multi_label(SampledTrueLabelTraining, Option, KNNList, TrueLabelTraining);
    AvgHammingTraining = AvgHammingTraining + RecoveredResult.HammingLoss;

    % Test
    K = 10;

    %%% AllSampledRecovered
    [ResultAllSampledRecovered.Prior, ResultAllSampledRecovered.PriorN, ResultAllSampledRecovered.Cond, ResultAllSampledRecovered.CondN] = MLKNN_train(AllDataTraining, RecoveredResult.RecoveredLabel', K, 1);
    [ResultAllSampledRecovered.HammingLoss, ResultAllSampledRecovered.RankingLoss, ResultAllSampledRecovered.OneError, ResultAllSampledRecovered.Coverage, ResultAllSampledRecovered.Average_Precision, ResultAllSampledRecovered.Outputs, ResultAllSampledRecovered.Pre_Labels] = MLKNN_test(AllDataTraining, RecoveredResult.RecoveredLabel', AllDataTesting, TrueLabelTesting', K, ResultAllSampledRecovered.Prior, ResultAllSampledRecovered.PriorN, ResultAllSampledRecovered.Cond, ResultAllSampledRecovered.CondN);
    [ResultAllSampledRecovered.ConfusionMatrix, ResultAllSampledRecovered.TP, ResultAllSampledRecovered.FN, ResultAllSampledRecovered.FP, ResultAllSampledRecovered.TN] = Ddavid_get_confusion_matrix(TrueLabelTesting, ResultAllSampledRecovered.Pre_Labels');
    
    AvgHammingTestingAllSampledRecovered = AvgHammingTestingAllSampledRecovered + ResultAllSampledRecovered.HammingLoss;

    % Recover training labels with II
    Option.IncludeInstanceItself = true;

    [RecoveredResultII] = Ddavid_kNN_recover_multi_label(SampledTrueLabelTraining, Option, KNNList, TrueLabelTraining);
    AvgHammingTrainingII = AvgHammingTrainingII + RecoveredResultII.HammingLoss;

    % Test
    K = 10;

    %%% AllSampledRecovered
    [ResultAllSampledRecoveredII.Prior, ResultAllSampledRecoveredII.PriorN, ResultAllSampledRecoveredII.Cond, ResultAllSampledRecoveredII.CondN] = MLKNN_train(AllDataTraining, RecoveredResultII.RecoveredLabel', K, 1);
    [ResultAllSampledRecoveredII.HammingLoss, ResultAllSampledRecoveredII.RankingLoss, ResultAllSampledRecoveredII.OneError, ResultAllSampledRecoveredII.Coverage, ResultAllSampledRecoveredII.Average_Precision, ResultAllSampledRecoveredII.Outputs, ResultAllSampledRecoveredII.Pre_Labels] = MLKNN_test(AllDataTraining, RecoveredResultII.RecoveredLabel', AllDataTesting, TrueLabelTesting', K, ResultAllSampledRecoveredII.Prior, ResultAllSampledRecoveredII.PriorN, ResultAllSampledRecoveredII.Cond, ResultAllSampledRecoveredII.CondN);
    [ResultAllSampledRecoveredII.ConfusionMatrix, ResultAllSampledRecoveredII.TP, ResultAllSampledRecoveredII.FN, ResultAllSampledRecoveredII.FP, ResultAllSampledRecoveredII.TN] = Ddavid_get_confusion_matrix(TrueLabelTesting, ResultAllSampledRecoveredII.Pre_Labels');
    
    AvgHammingTestingAllSampledRecoveredII = AvgHammingTestingAllSampledRecoveredII + ResultAllSampledRecoveredII.HammingLoss;

end

AvgHammingTraining = AvgHammingTraining / ExperimentTimes;
AvgHammingTestingAllSampledRecovered = AvgHammingTestingAllSampledRecovered / ExperimentTimes;
AvgHammingTestingAllSampledRecoveredII = AvgHammingTestingAllSampledRecoveredII / ExperimentTimes;

disp(['Average Hamming Loss of recovered training data = ' num2str(AvgHammingTraining)]);
disp(['Average Hamming Loss of all recovered testing data = ' num2str(AvgHammingTestingAllSampledRecovered)]);
disp(['Average Hamming Loss of all recovered testing data with II = ' num2str(AvgHammingTestingAllSampledRecoveredII)]);

save([Name '_' int2str(SampledDataPercent) '_' int2str(SampledLabelPercent) '_ExpermentResult']);
